(define-module (sudoku board))

(use-modules (srfi srfi-1)
             (sudoku square))

(define-public (make-board)
  (make-array (make-square) 9 9))

(define-public (set-square board square i j)
  (array-set! board square i j)
  board)

(define-public (get-row board i)
  (let loop ((j 0) (row '()))
    (if (array-in-bounds? board i j)
      (loop (1+ j)
            (cons (array-ref board i j) row))
      (reverse row))))

(define-public (set-row board row i)
  (fold (lambda (square j n-board)
          (array-set! n-board square i j)
          n-board)
        board
        row
        (iota 9)))

(define-public (get-col board j)
  (let loop ((i 0) (col '()))
    (if (array-in-bounds? board i j)
      (loop (1+ i)
            (cons (array-ref board i j) col))
      (reverse col))))

(define-public (set-col board col j)
  (fold (lambda (square i n-board)
          (array-set! n-board square i j)
          n-board)
        board
        col
        (iota 9)))

(define-public (get-box board n)
  (let ((x (* 3 (quotient n 3)))
        (y (* 3 (modulo n 3))))
    (reverse
      (fold (lambda (i l)
              (cons (array-ref
                      board
                      (+ x (quotient i 3))
                      (+ y (modulo i 3)))
                    l))
            '()
            (iota 9)))))

(define-public (set-box board box n)
  (let ((x (* 3 (quotient n 3)))
        (y (* 3 (modulo n 3))))
    (fold (lambda (square i n-board)
            (array-set! n-board
                        square
                        (+ x (quotient i 3))
                        (+ y (modulo i 3)))
            n-board)
          board
          box
          (iota 9))))
